package org.example.collection.hashmap;

import org.junit.Test;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.function.BiConsumer;

/**
 * Hashmap的七种遍历方式
 *
 * EntrySet 之所以比 KeySet 的性能高是因为，KeySet 在循环时使用了 map.get(key)，
 * 而 map.get(key) 相当于又遍历了一遍 Map 集合去查询 key 所对应的值。为什么要用“又”这个词？
 * 那是因为在使用迭代器或者 for 循环时，其实已经遍历了一遍 Map 集合了，因此再使用 map.get(key) 查询时，相当于遍历了两遍。
 *
 * 而 EntrySet 只遍历了一遍 Map 集合，之后通过代码“Entry<Integer, String> entry = iterator.next()”把对象的 key 和 value 值都放入到了 Entry 对象中，
 * 因此再获取 key 和 value 值时就无需再遍历 Map 集合，只需要从 Entry 对象中取值就可以了。
 *
 * 所以，EntrySet 的性能比 KeySet 的性能高出了一倍，因为 KeySet 相当于循环了两遍 Map 集合，而 EntrySet 只循环了一遍。
 *
 * 关于遍历中删除数据：
 * 我们不能在遍历中使用集合 map.remove() 来删除数据，这是非安全的操作方式，但我们可以使用迭代器的 iterator.remove() 的方法来删除数据，
 * 这是安全的删除集合的方式。同样的我们也可以使用 Lambda 中的 removeIf 来提前删除数据，或者是使用 Stream 中的 filter 过滤掉要删除的数据进行循环，
 * 这样都是安全的，当然我们也可以在 for 循环前删除数据在遍历也是线程安全的。
 */
public class TransversalTest {

    private static Map<Integer, String> map = new HashMap();

    static {
        map.put(1, "Java");
        map.put(2, "JDK");
        map.put(3, "Spring Framework");
        map.put(4, "MyBatis framework");
        map.put(5, "Java中文社群");
    }

    // 迭代器EntrySet
    @Test
    public void Test01 () {
        Iterator<Map.Entry<Integer, String>> iterator = map.entrySet().iterator();

        while (iterator.hasNext()) {
            Map.Entry<Integer, String> e = iterator.next();

            System.out.println(e.getKey());
            System.out.println(e.getValue());
        }
    }

    // 迭代器 KeySet
    @Test
    public void Test02 () {
        Iterator<Integer> iterator = map.keySet().iterator();
        while (iterator.hasNext()) {
            Integer key = iterator.next();
            System.out.println(key);
            System.out.println(map.get(key));
        }
    }

    //ForEach EntrySet
    @Test
    public void Test03 () {
        for (Map.Entry<Integer, String> entry : map.entrySet()) {
            System.out.println(entry.getKey());
            System.out.println(entry.getValue());
        }
    }


    //ForEach KeySet
    @Test
    public void test04 () {
        for (Integer key : map.keySet()) {
            System.out.println(key);
            System.out.println(map.get(key));
        }
    }

    // Lambda
    @Test
    public void test05 () {
        // 遍历
        map.forEach((key, value) -> {
            System.out.println(key);
            System.out.println(value);
        });
    }

    // Streams API 单线程
    @Test
    public void test06 () {
        map.entrySet().stream().forEach((entry)-> {
            System.out.println(entry.getKey());
            System.out.println(entry.getValue());
        });
    }

    // Streams API 多线程
    @Test
    public void test07 () {
        map.entrySet().parallelStream().forEach((entry -> {
            System.out.println(entry.getKey());
            System.out.println(entry.getValue());
        }));
    }
}
